﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Data.OracleClient;
using System.Xml;
using Meqs.Entity;
using Meqs.Entity.Views;
using Meqs.Logic.Core;
using Meqs.Logic.Interface;

namespace Meqs.Logic.Implement.MsSql
{

    /// <summary>
    /// 评教系统报表逻辑层
    /// </summary>
    public class EvalReportLogic : BaseSqlMapDao, IEvalReportLogic
    {
        private readonly IStudentInfoLogic _studentLogic;

        private static IList<CacheEntity> _cacheEntityList = new List<CacheEntity>();

        public EvalReportLogic(IStudentInfoLogic studentLogic)
        {
            _studentLogic = studentLogic;
        }
        /// <summary>
        /// 获取答案列表
        /// </summary>
        /// <param name="evalSheetID"></param>
        /// <param name="qiId"></param>
        /// <param name="schoolMark"></param>
        /// <returns></returns>
        public AnswerEntity GetAnswerList(int evalSheetID, int qiId, string schoolMark)
        {
            IDBAccess dbAccess = DBAccessFactory.CreateInstance(DBType.MsSQL);
            try
            {
                dbAccess.Init(ConnectionString);
                dbAccess.Open();
                string sql = "select detail from {0}.SheetItems where esid = {1}";
                sql = string.Format(sql, schoolMark, evalSheetID);
                DataTable dt = dbAccess.RunQuery(sql);
                int count = dt.Rows.Count;
                if (count == 0)
                    return null;

                sql = "select qitype from {0}.questionitems where rid = {1}";
                sql = string.Format(sql, schoolMark, qiId);
                DataTable d = dbAccess.RunQuery(sql);
                int qiType = int.Parse(d.Rows[0][0].ToString());
                if (qiType == 1)
                {
                    sql = "select count(t.rid) from {0}.sheetitems t where t.esid = {1}";
                    sql = string.Format(sql, schoolMark, evalSheetID);
                    d = dbAccess.RunQuery(sql);
                    int replyNum = int.Parse(d.Rows[0][0].ToString());
                    // 问答题
                    IList<string> replyList = new List<string>();
                    foreach (DataRow row in dt.Rows)
                    {
                        string detail = row[0].ToString();
                        XmlDocument doc = new XmlDocument();
                        doc.LoadXml(detail);

                        XmlNode replyNode = doc.SelectSingleNode("//items/item[@id=\"" + qiId + "\"]/reply");
                        if (replyNode == null) continue;
                        replyList.Add(replyNode.InnerXml);
                    }
                    AnswerEntity ae = new AnswerEntity(qiId, qiType, 0, 0, 0, replyNum, replyList);
                    return ae;
                }
                else
                {
                    // 选择、得分题
                    double allScore = 0;
                    double allMaxScore = 0;
                    foreach (DataRow row in dt.Rows)
                    {
                        string detail = row[0].ToString();
                        XmlDocument doc = new XmlDocument();
                        doc.LoadXml(detail);

                        XmlNode scoreNode = doc.SelectSingleNode("//items/item[@id=\"" + qiId + "\"]/score");
                        if (scoreNode == null) continue;
                        double score = double.Parse(scoreNode.InnerXml);
                        allScore += score;

                        XmlNode maxNode = doc.SelectSingleNode("//items/item[@id=\"" + qiId + "\"]/max");
                        if (maxNode == null) continue;
                        double max = double.Parse(maxNode.InnerXml);
                        allMaxScore += max;
                    }
                    double avgScore = allScore / count;
                    double maxScore = allMaxScore / count;
                    double avgPercent = maxScore == 0 ? 0 : avgScore / maxScore;
                    AnswerEntity ae = new AnswerEntity(qiId, qiType, avgScore, avgPercent, maxScore, 0, null);
                    return ae;
                }
            }
            catch (Exception)
            {
                return null;
            }
            finally
            {
                dbAccess.Close();
            }
        }

        /// <summary>
        /// 获取答案列表
        /// </summary>
        /// <param name="studentEvalID"></param>
        /// <param name="studentID"></param>
        /// <param name="qiId"></param>
        /// <param name="schoolMark"></param>
        /// <returns></returns>
        public AnswerEntityExtend GetAnswerListByStudentEval(int studentEvalID, int studentID, int qiId, string schoolMark)
        {
            IDBAccess dbAccess = DBAccessFactory.CreateInstance(DBType.MsSQL);
            try
            {
                dbAccess.Init(ConnectionString);
                dbAccess.Open();
                string sql = "select detail from {0}.QualitySheetItems where SEID = {1} and  AUTHORID = {2}";
                sql = string.Format(sql, schoolMark, studentEvalID, studentID);
                DataTable dt = dbAccess.RunQuery(sql);
                int count = dt.Rows.Count;
                if (count == 0)
                    return null;

                sql = "select qitype from {0}.questionitems where rid = {1}";
                sql = string.Format(sql, schoolMark, qiId);
                DataTable d = dbAccess.RunQuery(sql);
                int qiType = int.Parse(d.Rows[0][0].ToString());
                if (qiType == 1)
                {
                    sql = "select count(t.rid) from {0}.QualitySheetItems t where t.SEID = {1} and  AUTHORID = {2}";
                    sql = string.Format(sql, schoolMark, studentEvalID, studentID);
                    d = dbAccess.RunQuery(sql);
                    int replyNum = int.Parse(d.Rows[0][0].ToString());
                    // 问答题
                    IList<string> replyList = new List<string>();
                    foreach (DataRow row in dt.Rows)
                    {
                        string detail = row[0].ToString();
                        XmlDocument doc = new XmlDocument();
                        doc.LoadXml(detail);

                        XmlNode replyNode = doc.SelectSingleNode("//items/item[@id=\"" + qiId + "\"]/reply");
                        if (replyNode == null) continue;
                        replyList.Add(replyNode.InnerXml);
                    }
                    double avgClsScore = CalculateClsAvgScore(studentID, qiId, schoolMark, dbAccess);
                    AnswerEntityExtend ae = new AnswerEntityExtend(qiId, qiType, 0, 0, 0, replyNum, replyList, avgClsScore);
                    return ae;
                }
                else
                {
                    // 选择、得分题
                    double allScore = 0;
                    double allMaxScore = 0;
                    foreach (DataRow row in dt.Rows)
                    {
                        string detail = row[0].ToString();
                        XmlDocument doc = new XmlDocument();
                        doc.LoadXml(detail);

                        XmlNode scoreNode = doc.SelectSingleNode("//items/item[@id=\"" + qiId + "\"]/score");
                        if (scoreNode == null) continue;
                        double score = double.Parse(scoreNode.InnerXml);
                        allScore += score;

                        XmlNode maxNode = doc.SelectSingleNode("//items/item[@id=\"" + qiId + "\"]/max");
                        if (maxNode == null) continue;
                        double max = double.Parse(maxNode.InnerXml);
                        allMaxScore += max;
                    }
                    double avgScore = allScore / count;
                    double maxScore = allMaxScore / count;
                    double avgPercent = maxScore == 0 ? 0 : avgScore / maxScore;
                    double avgClsScore = CalculateClsAvgScore(studentID, qiId, schoolMark, dbAccess);
                    AnswerEntityExtend ae = new AnswerEntityExtend(qiId, qiType, avgScore, avgPercent, maxScore, 0, null, avgClsScore);
                    return ae;
                }
            }
            catch (Exception)
            {
                return null;
            }
            finally
            {
                dbAccess.Close();
            }
        }

        protected double CalculateClsAvgScore(int studentID, int qiID, string schoolMark, IDBAccess dbAccess)
        {
            StudentInfo student = _studentLogic.FindById(studentID);
            int clsID = student.ClsID;

            CacheEntity tempCe = new CacheEntity(clsID, qiID, studentID, 0);
            if (_cacheEntityList.Contains(tempCe))
            {
                CacheEntity ce = _cacheEntityList[_cacheEntityList.IndexOf(tempCe)];
                return ce.Score;
            }

            Hashtable ht = new Hashtable();
            ht.Add("ClsID", clsID);
            ht.Add("SchoolMark", schoolMark);
            IList<StudentInfo> list = _studentLogic.FindAll(ht);
            if (list.Count == 0) return 0;

            double avgClsScore = 0;
            foreach (StudentInfo info in list)
            {
                string sql = "select detail from {0}.QualitySheetItems where AUTHORID = {1}";
                sql = string.Format(sql, schoolMark, info.RID);
                double qiScore = 0;
                DataTable dt = dbAccess.RunQuery(sql);
                foreach (DataRow row in dt.Rows)
                {
                    string detail = row[0].ToString();
                    XmlDocument doc = new XmlDocument();
                    doc.LoadXml(detail);

                    XmlNode scoreNode = doc.SelectSingleNode("//items/item[@id=\"" + qiID + "\"]/score");
                    if (scoreNode == null) continue;
                    double score = double.Parse(scoreNode.InnerXml);
                    qiScore += score;
                }
                double avgScore = dt.Rows.Count == 0 ? 0 : qiScore/dt.Rows.Count;
                avgClsScore += avgScore;
            }
            avgClsScore = avgClsScore/list.Count;

            CacheEntity entity = new CacheEntity(clsID, qiID, studentID, avgClsScore);
            _cacheEntityList.Add(entity);

            return avgClsScore;
        }

        private class CacheEntity
        {
            private int _clsID;
            private int _qiID;
            private int _studentID;
            private double _score;

            public CacheEntity()
            {
            }

            public CacheEntity(int clsID, int qiID, int studentID, double score)
            {
                _clsID = clsID;
                _qiID = qiID;
                _studentID = studentID;
                _score = score;
            }

            public int ClsID
            {
                get { return _clsID; }
                set { _clsID = value; }
            }

            public int QiID
            {
                get { return _qiID; }
                set { _qiID = value; }
            }

            public int StudentID
            {
                get { return _studentID; }
                set { _studentID = value; }
            }

            public double Score
            {
                get { return _score; }
                set { _score = value; }
            }

            public bool Equals(CacheEntity other)
            {
                if (ReferenceEquals(null, other)) return false;
                if (ReferenceEquals(this, other)) return true;
                return other._clsID == _clsID && other._qiID == _qiID && other._studentID == _studentID;
            }

            public override bool Equals(object obj)
            {
                if (ReferenceEquals(null, obj)) return false;
                if (ReferenceEquals(this, obj)) return true;
                if (obj.GetType() != typeof (CacheEntity)) return false;
                return Equals((CacheEntity) obj);
            }

            public override int GetHashCode()
            {
                unchecked
                {
                    int result = _clsID;
                    result = (result*397) ^ _qiID;
                    result = (result*397) ^ _studentID;
                    return result;
                }
            }
        }
    }
}
